DeepSeek FP8 Training
Table of Contents
1. Overview  ATTACH
1.1. FP8 GEMM Pipeline
DeepSeek V3 implemented FP8 GEMM operator for training, i.e., keep params in FP8 during training. However, given that some operators require full precision to keep stability during computation, DeepSeek V3 maintains full precision or half precision (FP32 or BF16) on several operators: Embedding layer, Output Head, MoE Gating, Normalization, Attention Module. Only linear layers uses FP8 GEMM.
The overall training adopts mixed precision schema. Besides FP8 quantized weights, master weights, weight gradients and optimizer states are still stored with higher precision, and are dynamically casted to lower precision for computation.
For example, the above illustrates the FP8 computation pipeline:
- Activition from previous layer in BF16 format is quantized to FP8
- Master weight (FP32) is quantized to FP8. Then the quantized version is involved in FP8 GEMM.
- FP8 GEMM computes intermediate results (tile-based computation), and accumulates them with FP32 register for accuracy concerns.
- Then, the result in FP32 is quantized to BF16 and stored to output matrix.
During backward propagation, to update the weight:
- The gradient of output from next layer (BF16) is quantized to FP8. Also, the activition matrix (input) is also quantized to FP8 and sent to
WgradFP8 GEMM. We also use FP32 accumulator due to precision concerns. - The output is Weight Gradient. We store it in FP32. Later, the gradient is converted to BF16 to update the optimizer states.
- The optimizer states are transformed to FP32 to update master weight.
On the other side, to get the gradient of input:
- The master weight is converted to FP8. The output gradient is also converted to FP8. These 2 matrices are passed to FP8 GEMM operator for
Dgrad. We also use FP32 for accumulator. - The result is quantized to BF16 to obtain Input Gradient. The backprop continues.
1.2. Fine-grained FP8 GEMM Implementation
The challenge of implementing FP8 GEMM kernel includes
- underflow and overflow
- presence of outliers in activition, weights and gradients
So DeepSeek’s solution for this is fine-grained quantization that quantize values within smaller groups.
- tile-wise \(1\times N_c\) grouping for activition
- block-wise \(N_c \times N_c\) grouping for weights
Why different grouping size for activition and weight? The paper says the reason is that Dgrad is sensitive to precision, \(N_c\times N_c\) blockwise quantization will make model diverge on MoE. In addition, “activition gradients are highly imbalanced among tokens, resulting in token-correlated outliers”, as suggested by paper.
1.3. Accumulation Precision
1.3.1. Pipeline Parallelism
DeepSeek’s FP8 GEMM involves 2 steps:
- quantize master weight into FP8, and execute FP8 GEMM
- move FP8 intermediate results to CUDA Core for FP32 accumulation
These 2 steps can benefit from pipeline parallelism for instruction overlap to maintain high utilization of Tensor Cores.
1.3.2. Mantissa over Exponents
Use FP8 E4M3 globally for more precision information. This is also important for fine-grained quantization, because exponents can be effectively shared within same small group.
1.3.3. Online Quantization
To cooperate with pipeline parallelism and reduce memory consumption, absmax required by quantization is computed online, as well as the quantization itself.